package com.csea;

import com.csea.impl.IMessageFormatImpl;
import com.csea.impl.UserCredentialImpl;

import java.util.UUID;
import java.util.function.*;

/**
 * @author Csea
 * @title
 * @date 2019/12/11 19:57
 */
public class App {
    public static void main(String[] args) {
        UserCredential user = new UserCredentialImpl();
        System.out.println(user.verifyUser("admin"));
        System.out.println(user.getCredential("manager"));


        String msg = "CseaNB";
        if (IMessageFormat.verifyMessage(msg)) {
            IMessageFormat format = new IMessageFormatImpl();
            System.out.println(format.format(msg, "json"));
        }

        // 匿名内部类，实现接口的抽象方法
        UserCredential ic = new UserCredential() {
            @Override
            public String verifyUser(String username) {
                return "admin".equals(username) ? "管理员" : "会员";
            }
        };

        System.out.println(ic.verifyUser("manager"));
        System.out.println(ic.verifyUser("admin"));

        // lambda 表达式，针对函数式接口的简单实现
        UserCredential ic2 = (String username) -> {
            return "admin".equals(username) ? "lambda管理员" : "lambda会员";
        };

        System.out.println(ic2.verifyUser("admin"));
        System.out.println(ic2.verifyUser("manager"));

        //接收参数T，返回boolean
        Predicate<String> pre = (String username) -> {
            return "admin".equals(username);
        };
        System.out.println(pre.test("admin"));
        System.out.println(pre.test("manager"));

        //接收参数T，没有返回值
        Consumer<String> con = (String message) -> {
            System.out.println("发送的消息是：" + message);
            System.out.println("发送完毕");
        };
        con.accept("nice");
        con.accept("CseaNB");

        //接收参数T对象，返回R对象
        Function<String, Integer> fun = (String gender) -> {
            return "male".equals(gender) ? 1 : 0;
        };
        System.out.println(fun.apply("male"));
        System.out.println(fun.apply("female"));

        //不接收任何参数，直接通过get获取指定类型对象
        Supplier<String> sup = () -> {
            return UUID.randomUUID().toString();
        };
        System.out.println(sup.get());
        System.out.println(sup.get());
        System.out.println(sup.get());

        // 接收参数对象T，返回结果对象T
        UnaryOperator<String> uo = (String img) -> {
            img += "[100*200]";
            return img;
        };
        System.out.println(uo.apply("原图--"));

        // 接收两个T对象，返回一个T对象结果
        BinaryOperator<String> bo = (String firstname, String lastname) -> {
            firstname += "Csea";
            lastname += "NB";
            return firstname + lastname;
        };
        System.out.println(bo.apply("first", "last"));

        /**
         * java.util.function 提供大量的函数式接口
         * Predicate接收参数T，返回boolean
         * Consumer接收参数T，没有返回值
         * Function接收参数T对象，返回R对象
         * Supplier不接收任何参数，直接通过get获取指定类型对象
         * UnaryOperator接收参数T对象，执行业务处理之后，返回更新之后的T对象
         * BinaryOperator接收两个T对象，执行业务处理后，返回一个T对象
         */


        // lambda 表达式的基本语法
        /**
         * 声明：和lambda表达式绑定的接口类型
         * 参数：包含在一对圆括号中，和绑定的接口中的抽象方法中的参数个数及顺序一致
         * 操作符：->
         * 执行代码块：包含在一对大括号中，出现在操作符号的右侧
         *
         * 接口声明：（参数） -> {执行代码块}
         */

        ILambda iLambda1 = () -> {
            System.out.println("Csea");
            System.out.println("NB");
        };
        iLambda1.test();

        // 如果执行代码块只有一行，可以省略{}
        ILambda iLambda2 = () -> System.out.println("iLambda2");
        iLambda2.test();

        ILambda2 iLambda21 = (String n, int a) -> {
            System.out.println("name:" + n + " age " + a);
        };
        iLambda21.test("Csea", 22);

        // 这里Lambda会自动识别参数类型
        ILambda2 iLambda22 = (n, a) -> {
            System.out.println("name: " + n + " age " + a);
        };
        iLambda22.test("Csea", 22);

        ILambda3 iLambda3 = (x, y) -> {
            return x + y;
        };
        System.out.println(iLambda3.test(1, 2));

        // 如果只有一行代码块，还可以省略return
        ILambda3 iLambda31 = (x, y) -> x + y;
        System.out.println(iLambda31.test(3, 3));

        /**
         * lambda表达式，必须和接口绑定
         * lambda表达式的参数，可以附带0个到n个参数，括号在的参数类型可以不用指定，JVM在运行时，会自动根据绑定的抽象方法中的自动推导
         * lambda表达式的返回值，如果代码块只有一行，并且没有大括号，不用写return关键字，单行代码的执行结果，会自动返回，
         * 若果添加了大括号，或者有多行代码，必须通过return关键词返回结果
         */
    }

    /**
     * 没有参数，没有返回值的lambda表达式绑定的接口
     */
    interface ILambda {
        void test();
    }

    /**
     * 带有参数，没有返回值的lambda表达式
     */
    interface ILambda2 {
        void test(String name, int age);
    }

    /**
     * 带有参数，带有返回值的lambda表达式
     */
    interface ILambda3 {
        Integer test(Integer x, Integer y);
    }
}
